#include "ThreadPool/ThreadPool.h"
#include "Logger.h"

ThreadPool& ThreadPool::getInstance()
{
	static ThreadPool instance;
	return instance;
}

bool ThreadPool::init(int num)
{
	std::unique_lock<std::mutex> lock(mMux);
	this->mThreadNum = num;
	INFOLOGGER("Thread Inited success");
	return true;
}

bool ThreadPool::start()
{
	if (this->mThreadNum < 0)
	{
		ERRORLOGGER("Please Init!");
		return false;
	}
	if (!mThreadList.empty())
	{
		INFOLOGGER("Thread has been Inited");
		return true;
	}
	for (int i = 0; i != mThreadNum; i++)
	{
		auto th = std::make_shared<std::thread>(&ThreadPool::run, this);
		mThreadList.push_back(th);
	}
	INFOLOGGER("has created %d threads", mThreadNum);
	return true;
}

void ThreadPool::stop()
{
	mIsExit = true;
	mCv.notify_all();
	for (auto& th : mThreadList)
	{
		th->join();
	}
	std::unique_lock<std::mutex> lock(mMux);
	mThreadList.clear();
}

void ThreadPool::addTask(std::shared_ptr<Task> task)
{
	std::unique_lock<std::mutex> lock(mMux);
	mTaskList.push_back(task);
	lock.unlock();
	mCv.notify_one();
	task->mIsExit = [this] {return this->isExit(); };
}

std::shared_ptr<Task> ThreadPool::getTask()
{
	std::unique_lock<std::mutex> lock(mMux);
	if (this->mTaskList.empty())
	{
		this->mCv.wait(lock);
	}
	if (this->isExit())
	{
		return nullptr;
	}
	if (this->mTaskList.empty())
	{
		return nullptr;
	}
	auto task = mTaskList.front();
	mTaskList.pop_front();
	return task;
}

bool ThreadPool::isExit()
{
	return this->mIsExit;
}

int ThreadPool::getTaskCount()
{
	return mTaskCount;
}

void ThreadPool::run()
{
	while (!this->isExit())
	{
		if (mTaskList.empty())
			continue;
		auto task = this->getTask();
		if (!task)
			continue;
		++this->mTaskCount;
		try
		{
			task->run();
		}
		catch (...)
		{

		}
		--this->mTaskCount;
	}
}
